package com.yunhe.authority.repository.authority;

import com.yunhe.authority.domain.authority.Firm;
import com.yunhe.authority.domain.authority.User;
import com.yunhe.authority.domain.base.Theme;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * 用户Repository
 * @author liuronglei
 */
@Repository
public interface UserRepository extends Neo4jRepository<User, Long> {

    @Query("match(u:User) where ID(u)={id} set u.activity=false")
    void deleteUser(@Param("id") Long id);

    //    @Query("match p=(u:User)-[]-(r:Role) where u.name={name} and u.password={password} return p")
    User findByNameAndPassword(String name, String password);

    User findByName(String name);

    @Query("start user=node({userId}),role=node({roleId}) create (user)-[:HAS_ROLE]->(role)")
    void bindRole(@Param("userId") Long userId, @Param("roleId") Long roleId);

    @Query("start r=node({roleId}) match(u:User)-[:HAS_ROLE]->(r) where u.admin=true set u.admin=false with r match(u2:User)-[:HAS_ROLE]->(r) where ID(u2)={id} set u2.admin=true")
    void updateRoleAdmin(@Param("id") Long id, @Param("roleId") Long roleId);

    @Query("start user=node({userId}),role=node({roleId}) match(user)-[r:HAS_ROLE]->(role) delete r")
    void unbindRole(@Param("userId") Long userId, @Param("roleId") Long roleId);

    Page<User> findByActivity(boolean activity, Pageable pageable);

    Iterable<User> findByNameLikeOrTitleLike(String name, String title);

    Iterable<User> findByNameLikeOrTitleLike(String name, String title, Sort sort);

    Page<User> findByNameLikeOrTitleLike(String name, String title, Pageable pageable);

    Page<User> findByName(boolean activity, Pageable pageable);

    /**
     *根据服务名获得用户联系方式
     * @param serviceName 服务名称
     */
    @Query("match(u:User) where u.serviceName={serviceName} return u.phone")
    Iterable<String> findUserPhoneByServiceName(@Param("serviceName") String serviceName);

    /**
     * 根据用户ID获得主题
     * @param id 用户ID
     */
    @Query("start n=node({id}) match(n)-[:THEME_OF]->(theme) return theme")
    Theme findThemeByUserId(@Param("id") Long id);

    /**
     * 修改密码
     * @param id 用户ID
     * @param password 用户密码
     */
    @Query("start n=node({id}) set n.password={password} return n")
    User updatePassword(@Param("id") Long id, @Param("password") String password);

    @Query("match(u:User)-[:FIRM_OF]->(f:Firm) where ID(u)={userId} return f limit 1")
    Firm findFirmByUserId(@Param("userId") Long userId);

    @Query("match p=(t:Theme)<-[]-(u:User)-[:HAS_ROLE]->(r:Role) where ID(r)={roleId} return p")
    Iterable<User> findUsersByRoleId(@Param("roleId") Long roleId);

//    @Query("match p=(t1)<-[:THEME_OF|:HOMEPAGE_OF]-(u1:User)-[:HAS_ROLE]->(r1:Role)-[:HAS_CHILD*0..9]->" +
//            "(r2:Role)<-[:HAS_ROLE]-(u2:User)-[:THEME_OF|:HOMEPAGE_OF]-(t2) where ID(r1)={roleId} return p")
//    Iterable<User> findUsersByRootRoleId(@Param("roleId") Long roleId);

    @Query("match p=(t1)<-[:THEME_OF|:HOMEPAGE_OF]-(u1:User)-[:HAS_ROLE]->(r1:Role)where ID(r1)={roleId} return p")
    Iterable<User> findUsersByRoot(@Param("roleId") Long roleId);

    @Query("match p=(t1)<-[:THEME_OF|:HOMEPAGE_OF]-(u1:User{activity:true})-[:HAS_ROLE]->(r1:Role) where ID(r1)={roleId} return p")
    Iterable<User> findUsers(@Param("roleId") Long roleId);

    Iterable<User> findByTitleContaining(String title);

    Iterable<User> findByNameLikeOrTitleLikeOrPhoneLike(String name, String title, String phone);

    @Query("match(u:User)-[*0..9]->(r:Role)<-[]-(u2:User) where ID(u)={id} return u,u2")
    Iterable<User> findAllById(@Param("id") Long id);

    User findByPhone(String phone);

    Iterable<User> findByTitleLike(String title);

    @Query("match(u:User) where u.name in {nameList} return u")
    Iterable<User> findUsersByNames(@Param("nameList") List<String> nameList);

    @Query("match(u:User)-[]->(r:Role)-[:HAS_MENU]->(m:Menu{name:{menuName}}) return u")
    List<User> findUsersByMenu(@Param("menuName") String menuName);

    @Query("match(u:User)-[:HAS_ROLE]->(r:Role)-[:HAS_MENU]->(m:Menu) where m.name={menuName} return u")
    Iterable<User> findByMenuName(@Param("menuName") String menuName);

    /**
     * 根据单位id查询用户列表
     * @param firmId 单位ID
     * @param queryData 查询条件
     * @param pageable 分页对象
     * @return
     */
    @Query(value = " match(f:Firm)<-[:FIRM_OF]-(u:User) where id(f)={firmId} and (u.title contains {queryData} or u.phone contains {queryData}) return u order by u.sn asc",
            countQuery = " match(f:Firm)<-[:FIRM_OF]-(u:User) where id(f)={firmId} and (u.title contains {queryData} or u.phone contains {queryData}) return count(u)")
    Page<User> findByFirmId(@Param("firmId") Long firmId, @Param("queryData") String queryData, Pageable pageable);

    /**
     * 获得所有企业的用户列表
     * @param queryData 查询条件
     * @param pageable 分页对象
     * @return
     */
    @Query(value = " match p=(u:User)-[:COMPANY_OF]->(f:Company{activity:true}) where (u.title contains {queryData} or u.phone contains {queryData}) return p order by u.sn asc",
            countQuery = " match(f:Company{activity:true})<-[:COMPANY_OF]-(u:User) where (u.title contains {queryData} or u.phone contains {queryData}) return count(u)")
    Page<User> findAllCompanyUser(@Param("queryData") String queryData, Pageable pageable);

    User findByPhoneAndPassword(String phone, String encode);

    /**
     * 用户与项目进行绑定
     * @param userId
     * @param stationId
     */
    @Query("start user=node({userId}),station=node({stationId}) create (user)-[:HAS_STATION{activity:'1'}]->(station)")
    void bindStation(@Param("userId") Long userId,@Param("stationId") Long stationId);

    /**
     * 用户与项目组织进行绑定
     * @param userId
     * @param stationId
     * @param orgId
     */
    @Query("start user=node({userId}),organization=node({orgId}) create (user)-[:HAS_SYNERGY_ORG{stationId:{stationId}}]->(organization)")
    void bindStaionOrg(@Param("userId") Long userId,@Param("stationId") Long stationId,@Param("orgId") Long orgId);

    @Query("start user=node({userId}),organization=node({orgId}) create (user)-[:HAS_ORG{stationId:{stationId}}]->(organization)")
    void bindStaionAscriptionOrg(@Param("userId") Long userId,@Param("stationId") Long stationId,@Param("orgId") Long orgId);

    /**
     * 用户与项目角色绑定
     * @param userId
     * @param stationId
     * @param roleIds
     */
    @Query("MATCH(u:User),(r:Role) where ID(u)={userId} AND ID(r) IN {roleIds} CREATE (u)-[:HAS_ROLE{stationId:{stationId}}]->(r)")
    void bindStationRole(@Param("userId") Long userId,@Param("stationId") Long stationId, @Param("roleIds") List<Long> roleIds);

    /**
     * 用户与所有单位解绑
     * @param ids
     */
    @Query("match (u:User)-[r:FIRM_OF]->(f:Firm) where ID(u) IN {ids} delete r")
    void unbindAllFirms(@Param("ids") List<Long> ids);

    /**
     * 用户与所有项目解绑
     * @param ids
     */
    @Query("match (u:User)-[r:HAS_STATION]->(s:Station) where ID(u) IN {ids} delete r")
    void unbindAllStations(@Param("ids") List<Long> ids);

    /**
     * 用户与所有角色解绑
     * @param userIds
     */
    @Query("match (u:User)-[r:HAS_ROLE]->(role:Role) where ID(u) IN {userIds} delete r")
    void unbindAllRoles(@Param("userIds") List<Long> userIds);

    /**
     * 用户与所有组织解绑
     * @param ids
     */
    @Query("match (u:User)-[r:HAS_ORG]->(o:Organization) where ID(u) IN {ids} delete r")
    void unbindAllOrgs(@Param("ids") List<Long> ids);

    @Query("match (u:User)-[r:HAS_SYNERGY_ORG]->(o:Organization) where ID(u) IN {ids} delete r")
    void unbindAllSynergyOrgs(@Param("ids") List<Long> ids);

    /**
     * 通过id删除用户
     * @param ids
     */
    @Query("match (u:User) where ID(u) IN {ids} delete u")
    void deleteByIds(@Param("ids") List<Long> ids);

    /**
     * 禁用/恢复用户
     * @param userIds
     * @param activity
     * @param remark
     * @param format
     * @return
     */
    @Query("match (u:User) where ID(u) IN {ids} SET u.activity={activity},u.updateTime={updateTime},u.remark={remark} return  u")
    List<User> updateActivity(@Param("ids") List<Long> userIds, @Param("activity") String activity, @Param("remark") String remark, @Param("updateTime") String format);

    /**
     * 用户与单位进行绑定
     * @param id
     * @param firmId
     */
    @Query("start user=node({id}),firm=node({firmId}) create (user)-[:FIRM_OF{activity:'1'}]->(firm)")
    void bindFirms(@Param("id")Long id, @Param("firmId") Long firmId);

    /**
     * 用户与单位组织进行绑定
     * @param userId
     * @param firmId
     * @param orgId
     */
    @Query("start user=node({userId}),organization=node({orgId}) create (user)-[:HAS_SYNERGY_ORG{firmId:{firmId}}]->(organization)")
    void bindFirmOrg(@Param("userId") Long userId,@Param("firmId") Long firmId,@Param("orgId") Long orgId);

    @Query("start user=node({userId}),organization=node({orgId}) create (user)-[:HAS_ORG{firmId:{firmId}}]->(organization)")
    void bindFirmAscriptionOrg(@Param("userId") Long userId,@Param("firmId") Long firmId,@Param("orgId") Long orgId);

    /**
     * 用户与单位角色绑定
     * @param userId
     * @param firmId
     * @param roleIds
     */
    @Query("MATCH(u:User),(r:Role) where ID(u)={userId} AND ID(r) IN {roleIds} CREATE (u)-[:HAS_ROLE{firmId:{firmId}}]->(r)")
    void bindFirmRole(@Param("userId") Long userId,@Param("firmId") Long firmId, @Param("roleIds") List<Long> roleIds);

    /**
     * 校验单位是否已经关联用户
     * @param id
     * @param firmId
     * @return
     */
    @Query("MATCH(u:User)-[:FIRM_OF]->(f:Firm) where ID(u)={userId} and ID(f)={firmId} return u ")
    User findByUserIdAndFirmId(@Param("userId") Long id,@Param("firmId") Long firmId);

    /**
     * 校验项目是否已经关联用户
     * @param id
     * @param stationId
     * @return
     */
    @Query("MATCH(u:User)-[:HAS_STATION]->(s:Station) where ID(u)={userId} and ID(s)={stationId} return u ")
    User findByUserIdAndSationId(@Param("userId") Long id,@Param("stationId") Long stationId);

    /**
     * 解绑用户与对应单位的关系
     * @param id
     * @param firmId
     */
    @Query("match (u:User)-[r:FIRM_OF]->(f:Firm) where ID(u) ={userId} and ID(f)={firmId} delete r")
    void unbindUserAndFirm(@Param("userId") Long id,@Param("firmId") Long firmId);

    /**
     * 解绑用户与对应单位下所有角色的关系
     * @param id
     * @param firmId
     */
    @Query("match (u:User)-[r:HAS_ROLE{firmId:{firmId}}]->(role:Role) where ID(u)={userId} delete r")
    void unbindFirmUserAndRole(@Param("userId") Long id,@Param("firmId") Long firmId);

    /**
     * 解绑用户与对应单位下组织的关系
     * @param id
     * @param firmId
     */
    @Query("match (u:User)-[r:HAS_ORG{firmId:{firmId}}]->(o:Organization) where  ID(u)={userId} delete r")
    void unbindFirmUserAndOrg(@Param("userId") Long id,@Param("firmId") Long firmId);

    @Query("match (u:User)-[r:HAS_SYNERGY_ORG{firmId:{firmId}}]->(o:Organization) where  ID(u)={userId} delete r")
    void unbindFirmUserAndSynergyOrg(@Param("userId") Long id,@Param("firmId") Long firmId);

    /**
     * 解绑用户与项目的关系
     * @param id
     * @param stationId
     */
    @Query("match (u:User)-[r:HAS_STATION]->(s:Station) where ID(u)={userId} and ID(s)={stationId} delete r")
    void unbindUserAndStation(@Param("userId") Long id,@Param("stationId") Long stationId);

    /**
     * 解绑用户与对应电站下所有角色的关系
     * @param id
     * @param stationId
     */
    @Query("match (u:User)-[r:HAS_ROLE{stationId:{stationId}}]->(role:Role) where ID(u)={userId} delete r")
    void unbindStationUserAndRole(@Param("userId") Long id,@Param("stationId") Long stationId);

    /**
     * 解绑用户与对应电站下组织的关系
     * @param id
     * @param stationId
     */
    @Query("match (u:User)-[r:HAS_ORG{stationId:{stationId}}]->(o:Organization) where  ID(u)={userId} delete r")
    void unbindStationUserAndOrg(@Param("userId") Long id,@Param("stationId") Long stationId);

    @Query("match (u:User)-[r:HAS_SYNERGY_ORG{stationId:{stationId}}]->(o:Organization) where ID(u)={userId} delete r")
    void unbindStationUserAndSynergyOrg(@Param("userId") Long id,@Param("stationId") Long stationId);

    @Query("match (u:User{activity:'1'})-[r:HAS_ROLE]->(role:Role{name:{roleType}}) return u")
    Iterable<User> findByRoleType(@Param("roleType") String roleType);

    @Query("match(u:User)-[r:FIRM_OF]->(f:Firm) where ID(f)={firmId} and ID(u) IN {userIds} set r.activity={activity},r.remark={remark}")
    void updateFirmUserActivity(@Param("userIds") List<Long> userIds,@Param("firmId") Long firmId,
                                @Param("activity") String activity,@Param("remark") String remark);

    @Query("match(u:User)-[r:HAS_STATION]->(s:Station) where ID(s)={stationId} and ID(u) IN {userIds} set r.activity={activity},r.remark={remark}")
    void updateStationUserActivity(@Param("userIds") List<Long> userIds, @Param("stationId") Long stationId,
                                   @Param("activity") String activity,@Param("remark") String remark);

    @Query("match(u:User) where ID(u)={userId} set u.lastAccessProject={projectId},u.projectFlag={projectFlag} ")
    void updateLastProejct(@Param("userId") Long id,@Param("projectId") Long projectId,@Param("projectFlag") String projectFlag);

    @Query("match(o:Organization)<-[:HAS_ORG{stationId:{stationId}}]-(u:User{activity:'1'})-[:HAS_ROLE{stationId:{stationId}}]->(r:Role{name:{roleName}}) where ID(o)={orgId} return u")
    Iterable<User> getStationUserByOrgAndRoleName(@Param("orgId") Long orgId,@Param("roleName") String roleName,@Param("stationId") Long stationId);

    @Query("match(o:Organization)<-[:HAS_ORG{stationId:{stationId}}]-(u:User)-[:HAS_ROLE{stationId:{stationId}}]->(r:Role{name:{roleName}}) where ID(o) IN {orgIds} return u")
    Iterable<User> getStationUserByOrgsAndRoleName(@Param("orgIds") List<Long> orgIds,@Param("roleName") String roleName,@Param("stationId") Long stationId);

    @Query("match (u:User)-[r:HAS_STATION{activity:'1'}]->(s:Station) where ID(u)={userId} and ID(s)={stationId} return u")
    User findByUserIdAndStationId(@Param("userId") Long id,@Param("stationId") Long stationId);

    @Query("match (u:User)-[r:HAS_SYNERGY_ORG{firmId:{firmId}}]->(o:Organization) where  ID(u)={userId} and ID(o) = {orgId} delete r")
    void unbindFirmUserAndOrg(@Param("userId") Long id,@Param("firmId")  Long firmId,@Param("orgId") Long orgId);

    @Query("match (u:User)-[r:HAS_ORG{firmId:{firmId}}]->(o:Organization) where ID(u)={userId} and ID(o) = {orgId} delete r")
    void unbindFirmAscriptionOrg(@Param("userId") Long id,@Param("firmId") Long firmId, @Param("orgId") Long ascriptionOrgId);

    @Query("match (u:User)-[r:HAS_ROLE{firmId:{firmId}}]->(role:Role) where ID(u)={userId} and ID(role) = {roleId} delete r")
    void unbindFirmRole(@Param("userId") Long id,@Param("firmId") Long firmId,@Param("roleId") Long roleId);

    @Query("match (u:User)-[r:HAS_SYNERGY_ORG{stationId:{stationId}}]->(o:Organization) where  ID(u)={userId} and ID(o) = {orgId} delete r")
    void unbindStationUserAndOrg(@Param("userId") Long id,@Param("stationId") Long stationId,@Param("orgId") Long orgId);

    @Query("match (u:User)-[r:HAS_ORG{stationId:{stationId}}]->(o:Organization) where ID(u)={userId} and ID(o) = {orgId} delete r")
    void unbindStaionAscriptionOrg(@Param("userId")Long id,@Param("stationId") Long stationId,@Param("orgId") Long ascriptionOrgId);

    @Query("match (u:User)-[r:HAS_ROLE{stationId:{stationId}}]->(role:Role) where ID(u)={userId} and ID(role) = {roleId} delete r")
    void unbindStationRole(@Param("userId") Long id,@Param("stationId") Long stationId,@Param("roleId") Long roleId);

    @Query("match(o:Organization)<-[:HAS_ORG{stationId:{stationId}}]-(u:User{activity:'1'}) where ID(o)={orgId} return u")
    List<User> getUserByOrgIdAndStationId(@Param("orgId") Long orgId,@Param("stationId") Long stationId);

    @Query("match(o:Organization)<-[:HAS_SYNERGY_ORG{stationId:{stationId}}]-(u:User{activity:'1'}) where ID(o)={orgId} return u")
    List<User> getUserBySynergyOrgIdAndStationId(@Param("orgId") Long orgId,@Param("stationId") Long stationId);

    @Query("match (u:User)-[r:HAS_STATION{activity:'1'}]->(s:Station) where  ID(s)={stationId} return u")
    List<User> findStationUserByStationId(@Param("stationId") Long stationId);

    @Query("match (u:User)-[r:HAS_STATION{activity:'1'}]->(s:Station) where  ID(s)={stationId} AND u.title=~{userName}  return u")
    List<User> findStationUserByQueryCondition(@Param("stationId") Long stationId,@Param("userName") String userName);


//    @Query("match(f:Firm)<-[sr:FRIM_OF]-(u:User)-[:HAS_ROLE{firmId:{firmId}}]->(r:Role) where  ID(u)={id} AND ID(f)={firmId}" +
//            "RETURN DISTINCT  ID(u) as userId,u.title as title,u.name as name,u.phone as phone,ID(f) as firmId," +
//            "u.createTime as createTime,u.creator as creator,sr.activity as activity,sr.remark as remark  limit 1")
//    EmployeeUser getFirmUserById(@Param("id") Long id,@Param("firmId") Long firmId);
//
//    @Query("match(s:Station)<-[sr:HAS_STATION]-(u:User)-[:HAS_ROLE{stationId:{stationId}}]->(r:Role) where  ID(u)={id} AND ID(s)={stationId}" +
//            "RETURN DISTINCT ID(u) as userId,u.title as title,u.name as name,u.phone as phone,ID(s) as stationId," +
//            "u.createTime as createTime,u.creator as creator,sr.activity as activity,sr.remark as remark limit 1")
//    EmployeeUser getSationUserById(@Param("id") Long id,@Param("stationId") Long stationId);
}
